iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0
佛心分享-IT 人自學之術

靠近 ASP .NET Core 一點點系列 第 9

Day 9 Middleware : 自己動手做 Middleware 範例

  • 分享至 

  • xImage
  •  

前言
昨天針對 Middleware 做一個初步基本介紹 (順序性、運作原理等等),今天會針對如何製作出一個簡易 Middleware 來分享基本與進階作法。

分享主軸

  • 說明 Middleware (下)
  • 自建 Middleware 實作應用

ASP.NET Core 中的 Middleware

經過昨天後,都知道 Middleware 是在處理 ASP .NET Core 底層工作的中介,那他對於 ASP .NET Core 專案內,到底哪些算是所謂的 Middleware 呢 ?

  • 在 ASP .NET Core 內,使用 CreateBuilder() 建立一個 WebApplicationBuilder 物件
    var builder = WebApplication.CreateBuilder(args);

  • 然後所有要用到的服務,註冊到這邊 ( 把所有必要的服務註冊到 builder.Services 內,也就是IServiceCollection 內 )

  • 白話點就是,Middleware 是如下中間的範圍都是
    var app = builder.Build();
    ....
    app.Run();

( builder.Build()會是 WebApplication 類別 )

  • app.Run() 就會執行 Kestrel 的意思

  • 當 WebApplication 去註冊每一個 Middleware 的時候,就有順序性,不能擺錯,擺錯可能影響效能、安全性,所以專案內的 Middleware 不能隨意放置位置,要依照各個 Middleware 功能去決定放置順序

自己寫 Middleware 範例,兩種方法

第一種 : 創建類別把實作封裝起來,program.cs內註冊

public class RequestTimeoutMiddleware
{
    private readonly RequestDelegate _next; 
    private readonly TimeSpan _timeout; //欲要限制的超時時間

    public RequestTimeoutMiddleware(RequestDelegate next, TimeSpan timeout)
    {
        _next = next;
        _timeout = timeout;
    }

    //處理每個 HTTP 請求
    public async Task InvokeAsync(HttpContext context)
    {
        // 創建一個可以取消的
        using (var cts = new CancellationTokenSource())
        {
            // 創建一個延遲任務,表示超時時間
            var timeoutTask = Task.Delay(_timeout, cts.Token);

            // 執行下一個Middleware
            var requestTask = _next(context);

            // 等待請求任務或超時任務中的任意一個完成
            var completedTask = await Task.WhenAny(requestTask, timeoutTask);

            // 如果超時任務
            if (completedTask == timeoutTask)
            {
                // 設置 HTTP 狀態碼為 408(請求超時)
                context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
                // 返回超時消息
                await context.Response.WriteAsync("Request timed out.");
            }
            else
            {
                // 如果請求任務完成,取消超時任務
                cts.Cancel();
                // 等待請求任務完成
                await requestTask;
            }
        }
    }
}

Program.cs

var app = builder.Build();

    // 設置請求超時時間為 5 秒
    app.UseMiddleware<RequestTimeoutMiddleware>(TimeSpan.FromSeconds(5));

第二種 : 直接在註冊的地方寫實作

var app = builder.Build();

// 設置請求超時時間為 5 秒
app.Use(async (context, next) =>
{
    using (var cts = new CancellationTokenSource())
    {
        var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5), cts.Token);
        var requestTask = next(context);

        var completedTask = await Task.WhenAny(requestTask, timeoutTask);

        if (completedTask == timeoutTask)
        {
            context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
            await context.Response.WriteAsync("Request timed out.");
        }
        else
        {
            cts.Cancel();
            await requestTask;
        }
    }
});

app.Run();

兩種都可以跑,以上範例,自建一個Demo簡易的限制 Request 時間為5秒的 Middleware,若超過就返回,從這更可以得知 Middleware 可以做非常多事情,題外話 : 如果像是要取得更多應用層內的東西,這時候就可以使用 Filter 去實作 (今天不另外說明),會更為適合。

統整一下今日重點

  • Middleware 有兩種方式可以去自己創建 (這邊只是提供簡易範例,實作部分以及要做那些 Middleware 就是看不同專案需要用到那些合適的客製化 Middleware 了,也是有專案只需要內建 Middleware 的)
  • 對於 ASP .NET Core 來說,所謂 Middleware 範圍在哪裡

今日結語
了解昨天與今天內容,個人覺得可以大大增加對於何謂 Middleware 與運用上的掌握更加彈性與可控,這些觀念真的都非常重要!
明日繼續努力,希望今天也有幫助到大家,謝謝。


上一篇
Day 8 Middleware : 對於專案可以很靈活又擴充的中介軟體
下一篇
Day 10 DI:ASP.NET Core 中的核心設計模式,超重要!
系列文
靠近 ASP .NET Core 一點點13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言